﻿using System;
using System.Runtime.InteropServices;

namespace Yxinmt.Controls
{

    public class GifImage : System.Windows.Controls.Image
    {
        /// <summary>
        /// gif动画的System.Drawing.Bitmap
        /// </summary>
        private System.Drawing.Bitmap gifBitmap;

        /// <summary>
        /// 用于显示每一帧的BitmapSource
        /// </summary>
        private System.Windows.Media.Imaging.BitmapSource bitmapSource;

        public GifImage(string gifPath)
        {
            this.gifBitmap = new System.Drawing.Bitmap(gifPath);
            this.bitmapSource = this.GetBitmapSource();
            this.Source = this.bitmapSource;
        }

        /// <summary>
        /// 从System.Drawing.Bitmap中获得用于显示的那一帧图像的BitmapSource
        /// </summary>
        /// <returns></returns>
        private System.Windows.Media.Imaging.BitmapSource GetBitmapSource()
        {
            IntPtr handle = IntPtr.Zero;

            try
            {
                handle = this.gifBitmap.GetHbitmap();
                this.bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, System.Windows.Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
            }
            finally
            {
                if (handle != IntPtr.Zero)
                {
                    DeleteObject(handle);
                }
            }
            return this.bitmapSource;
        }

        /// <summary>
        /// Start animation
        /// </summary>
        public void StartAnimate()
        {
            System.Drawing.ImageAnimator.Animate(this.gifBitmap, this.OnFrameChanged);
        }

        /// <summary>
        /// Stop animation
        /// </summary>
        public void StopAnimate()
        {
            System.Drawing.ImageAnimator.StopAnimate(this.gifBitmap, this.OnFrameChanged);
        }

        /// <summary>
        /// Event handler for the frame changed
        /// </summary>
        private void OnFrameChanged(object sender, EventArgs e)
        {
            Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
            {
                try
                {
                    System.Drawing.ImageAnimator.UpdateFrames(); // 更新到下一帧
                    if (this.bitmapSource != null)
                    {
                        this.bitmapSource.Freeze();
                    }

                    //// Convert the bitmap to BitmapSource that can be display in WPF Visual Tree
                    this.bitmapSource = this.GetBitmapSource();
                    Source = this.bitmapSource;
                    this.InvalidateVisual();
                }
                catch (Exception ex)
                {
                    Utility.LoggerProxy.Exception("GifImage", "OnFrameChanged", ex);
                }
            }));
        }

        /// <summary>
        /// Delete local bitmap resource
        /// </summary>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool DeleteObject(IntPtr hObject);
    }
}
